[TAPDISK] honor read-only attributes when creating tap-based VBDs
authorJake Wires <jwires@xensource.com>
Sat, 24 Feb 2007 01:26:07 +0000 (17:26 -0800)
committerJake Wires <jwires@xensource.com>
Sat, 24 Feb 2007 01:26:07 +0000 (17:26 -0800)
Signed-off-by: Jake Wires <jwires@xensource.com>
tools/blktap/drivers/blktapctrl.c
tools/blktap/drivers/block-qcow.c
tools/blktap/drivers/tapdisk.c
tools/blktap/drivers/tapdisk.h
tools/blktap/lib/blktaplib.h
tools/blktap/lib/xenbus.c

index f2022fcc9755d396488b4b868822ee6aae3b9897..5f78cede2a41fc13da793c9e8b52848ec2ec7837 100644 (file)
@@ -303,6 +303,7 @@ static int write_msg(int fd, int msgtype, void *ptr, void *ptr2)
                msg->type = CTLMSG_PARAMS;
                msg->len = msglen;
                msg->drivertype = blkif->drivertype;
+               msg->readonly = blkif->readonly;
 
                gettimeofday(&timeout, NULL);
                msg->cookie = blkif->cookie;
@@ -410,7 +411,6 @@ static int read_msg(int fd, int msgtype, void *ptr)
        if (select(fd+1, &readfds,  (fd_set *) 0,
                  (fd_set *) 0, &timeout) > 0) {
                ret = read(fd, buf, msglen);
-               
        }                       
        if (ret > 0) {
                msg = (msg_hdr_t *)buf;
index 185c670111bc1ee21401ba63cbd0373ad599ec66..36f77e6f053ad68f723ef0bbbe794a447fd3d679 100644 (file)
@@ -422,7 +422,7 @@ static int qtruncate(int fd, off_t length, int sparse)
                return -1;
        if (S_ISBLK(st.st_mode))
                return 0;
-       
+
        sectors = (length + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE;
        current = (st.st_size + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE;
        rem     = st.st_size % DEFAULT_SECTOR_SIZE;
index 965dbd9b7d2223b2e75dc94c030282fba7843c39..954901b2a8f8eae3395761c718dea90e1d86bca6 100644 (file)
@@ -268,7 +268,8 @@ static int map_new_dev(struct td_state *s, int minor)
 }
 
 static struct disk_driver *disk_init(struct td_state *s, 
-                                    struct tap_disk *drv, char *name)
+                                    struct tap_disk *drv, 
+                                    char *name, td_flag_t flags)
 {
        struct disk_driver *dd;
 
@@ -285,14 +286,17 @@ static struct disk_driver *disk_init(struct td_state *s,
        dd->drv      = drv;
        dd->td_state = s;
        dd->name     = name;
+       dd->flags    = flags;
 
        return dd;
 }
 
-static int open_disk(struct td_state *s, struct tap_disk *drv, char *path)
+static int open_disk(struct td_state *s, 
+                    struct tap_disk *drv, char *path, td_flag_t flags)
 {
        int err;
        char *dup;
+       td_flag_t pflags;
        struct disk_id id;
        struct disk_driver *d;
 
@@ -301,16 +305,17 @@ static int open_disk(struct td_state *s, struct tap_disk *drv, char *path)
                return -ENOMEM;
 
        memset(&id, 0, sizeof(struct disk_id));
-       s->disks = d = disk_init(s, drv, dup);
+       s->disks = d = disk_init(s, drv, dup, flags);
        if (!d)
                return -ENOMEM;
 
-       err = drv->td_open(d, path, 0);
+       err = drv->td_open(d, path, flags);
        if (err) {
                free_driver(d);
                s->disks = NULL;
                return -ENOMEM;
        }
+       pflags = flags | TD_RDONLY;
 
        /* load backing files as necessary */
        while ((err = d->drv->td_get_parent_id(d, &id)) == 0) {
@@ -324,11 +329,11 @@ static int open_disk(struct td_state *s, struct tap_disk *drv, char *path)
                if (!dup)
                        goto fail;
 
-               new = disk_init(s, get_driver(id.drivertype), dup);
+               new = disk_init(s, get_driver(id.drivertype), dup, pflags);
                if (!new)
                        goto fail;
 
-               err = new->drv->td_open(new, new->name, TD_RDONLY);
+               err = new->drv->td_open(new, new->name, pflags);
                if (err)
                        goto fail;
 
@@ -342,6 +347,8 @@ static int open_disk(struct td_state *s, struct tap_disk *drv, char *path)
                free(id.name);
        }
 
+       s->info |= ((flags & TD_RDONLY) ? VDISK_READONLY : 0);
+
        if (err >= 0)
                return 0;
 
@@ -404,7 +411,8 @@ static int read_msg(char *buf)
                                goto params_done;
 
                        /*Open file*/
-                       ret = open_disk(s, drv, path);
+                       ret = open_disk(s, drv, path, 
+                                       ((msg->readonly) ? TD_RDONLY : 0));
                        if (ret)
                                goto params_done;
 
@@ -510,7 +518,8 @@ void io_done(struct disk_driver *dd, int sid)
 
        if (!run) return; /*We have received signal to close*/
 
-       if (drv->td_do_callbacks(dd, sid) > 0) kick_responses(dd->td_state);
+       if (sid > MAX_IOFD || drv->td_do_callbacks(dd, sid) > 0)
+               kick_responses(dd->td_state);
 
        return;
 }
@@ -661,6 +670,12 @@ static void get_io_request(struct td_state *s)
                        sector_nr = req->sector_number;
                }
 
+               if ((dd->flags & TD_RDONLY) && 
+                   (req->operation == BLKIF_OP_WRITE)) {
+                       blkif->pending_list[idx].status = BLKIF_RSP_ERROR;
+                       goto send_response;
+               }
+
                for (i = start_seg; i < req->nr_segments; i++) {
                        nsects = req->seg[i].last_sect - 
                                 req->seg[i].first_sect + 1;
@@ -726,10 +741,12 @@ static void get_io_request(struct td_state *s)
                        }
                        sector_nr += nsects;
                }
+       send_response:
                blkif->pending_list[idx].submitting = 0;
                /* force write_rsp_to_ring for synchronous case */
                if (blkif->pending_list[idx].secs_pending == 0)
-                       dd->early += send_responses(dd, 0, 0, 0, idx, (void *)0);
+                       dd->early += send_responses(dd, 0, 0, 0, idx, 
+                                                   (void *)(long)0);
        }
 
  out:
@@ -737,7 +754,7 @@ static void get_io_request(struct td_state *s)
        td_for_each_disk(s, dd) {
                dd->early += dd->drv->td_submit(dd);
                if (dd->early > 0) {
-                       io_done(dd, 10);
+                       io_done(dd, MAX_IOFD + 1);
                        dd->early = 0;
                }
        }
@@ -820,7 +837,8 @@ int main(int argc, char *argv[])
                                                dd->early += 
                                                        dd->drv->td_submit(dd);
                                                if (dd->early > 0) {
-                                                       io_done(dd, 10);
+                                                       io_done(dd, 
+                                                               MAX_IOFD + 1);
                                                        dd->early = 0;
                                                }
                                        }
index b76d46cce5d4aa10dc7f5c457d73277f9ce77416..5c68a5e9c8a3e2d0c28ab268d569fea449a002b5 100644 (file)
@@ -94,6 +94,7 @@ struct disk_driver {
        int early;
        char *name;
        void *private;
+       td_flag_t flags;
        int io_fd[MAX_IOFD];
        struct tap_disk *drv;
        struct td_state *td_state;
index 0ba3c04ec8cfb6125cf9e9b6f25e761f5c4e7e1d..078a2931857494cae851999f9e2ee73b41cac3c5 100644 (file)
@@ -173,6 +173,7 @@ typedef struct msg_hdr {
        uint16_t   len;
        uint16_t   drivertype;
        uint16_t   cookie;
+       uint8_t    readonly;
 } msg_hdr_t;
 
 typedef struct msg_newdev {
index d50e492784bc14f1751b2ac295bf35505123eb1c..fb36e748feed92b049ee495f35570f8df6e12d2f 100644 (file)
@@ -177,8 +177,11 @@ static void ueblktap_setup(struct xs_handle *h, char *bepath)
        }
 
        /* Check to see if device is to be opened read-only. */
-       asprintf(&path, "%s/%s", bepath, "read-only");
-       if (xs_exists(h, path))
+       deverr = xs_gather(h, bepath, "mode", NULL, &path, NULL);
+       if (deverr) {
+               DPRINTF("ERROR: could not find read/write mode\n");
+               goto fail;
+       } else if (path[0] == 'r')
                be->readonly = 1;
 
        if (be->blkif == NULL) {